#include <string.h>
#include <stdlib.h>

#include "communication.h"
#include "communication_core.h"
#include "list.h"
#include "log.h"

static int cmd_ioctl(struct communication_device *dev, unsigned int cmd, void *arg);


/**
 * @brief	通信协议初始化
 */
void communication_core_init(struct communication_core *p_communication_core)
{
    int count = 0;

    if (!p_communication_core) {
        DEBUG("PARAM ERROR!\r\n");
        return;
    }

    /* 初始化函数指针 */
    p_communication_core->ops.server_init_ops = sever_communication_init;
    p_communication_core->ops.send_data_ops = send_data;
    p_communication_core->ops.recv_data_ops = recv_data;
    p_communication_core->ops.analy_data_ops = analy_data;
    p_communication_core->ops.package_data_ops = package_data;

    /* 初始化fd的值 */
    p_communication_core->data.sendfd = 0;
    p_communication_core->data.recvfd = 0;

    /* 初始化协议的数据 */
    p_communication_core->data.send_data_packet.cmd_type = 0;
    p_communication_core->data.send_data_packet.cmd = 0;
    p_communication_core->data.send_data_packet.ack = 0;
    for (count = 0; count < DATA_MAX_NUM; count++)
        p_communication_core->data.send_data_packet.data[count] = NULL;

    p_communication_core->ioctl = cmd_ioctl;

    p_communication_core->dev.arg = 0;
    p_communication_core->dev.cmd = NONE;
}

/**
 * @brief	通信协议destory
 */
void communication_core_destory(struct communication_core *p_communication_core)
{
    int count;

    if (!p_communication_core) {
        DEBUG("PARAM ERROR!\r\n");
        return;
    }

    /* 销毁申请的内存 */
    for (count = 0; count < DATA_MAX_NUM; count++) {
        if (p_communication_core->data.recv_data_packet.data[count])
            free(p_communication_core->data.recv_data_packet.data[count]);
    }
}

/**
 * @brief	操作函数 
 */
static int cmd_ioctl(struct communication_device *dev, 
                    unsigned int cmd, void *arg)
{
    int ret;
    char *send_data = NULL;
    char *recv_data = NULL;
    uint16 send_length = 0;
    uint16 recv_length = 0;
    struct communication_core *p_core = NULL;

    if (!dev) {
        DEBUG("PARAM ERROR!\r\n");
        return (-COMM_PARAM_NULL);
    }

    p_core = container_of(dev, struct communication_core, dev);

    switch (cmd) {
        case COMM_SERVER_INIT:
            /* 服务端初始化 */
            if (p_core->ops.server_init_ops)
                ret = p_core->ops.server_init_ops();
            else
                ret = (-COMM_FUNC_NULL_ERR);
            break;

        case COMM_RECV:
            /* 接收数据 */
            if (p_core->ops.recv_data_ops && p_core->ops.analy_data_ops) {
                ret = p_core->ops.recv_data_ops(p_core->data.recvfd, 
                                                &recv_data, 
                                                &recv_length);
                if (ret == COMM_GET_ACK || ret == COMM_CLIENT_DISCONNECT)
                    break;
                if (ret < 0)
                    break;

                ret = p_core->ops.analy_data_ops(&p_core->data.recv_data_packet,
                                                recv_data,
                                                recv_length);
                free(recv_data);
                recv_data = NULL;

            } else
                ret = (-COMM_FUNC_NULL_ERR);

            break;

        case COMM_SEND:
            /* 发送数据 */
            if (p_core->ops.send_data_ops && p_core->ops.package_data_ops) {

                ret = p_core->ops.package_data_ops(&p_core->data.send_data_packet,
                                                   &send_data,
                                                   &send_length);
           
                ret = p_core->ops.send_data_ops(p_core->data.sendfd, 
                                                send_data,
                                                send_length);
                
                free(send_data);
                send_data = NULL;

            } else
                ret = (-COMM_FUNC_NULL_ERR);
            break;

        default:
            DEBUG("The cmd is error (%d).\r\n", cmd);
            ret = (-COMM_CMD_OVERSTEP_ERR);
            break;
    }

   return ret;
}

/* 销毁申请的数据包 */
void free_data_packet(struct data_packet *data)
{
    int count = 0;

    if (!data)
        return;

    data->cmd_type = 0;
    data->cmd = 0;
    data->ack = 0;
    for (count = 0; count < DATA_MAX_NUM; count++) {
        if (data->data[count] != NULL) {
            free(data->data[count]);
            data->data[count] = NULL;
        }
    }
}

/* 将数据包的数据赋值为0 */
void reset_data_packet(struct data_packet *data)
{
    int count = 0;

    if (!data)
        return;

    data->cmd_type = 0;
    data->cmd = 0;
    data->ack = 0;
    for (count = 0; count < DATA_MAX_NUM; count++) {
        data->data[count] = NULL;
    }
}

/* 复制数据包 */
bool cpy_data_packet(struct data_packet *tar, 
                     struct data_packet *src)
{
    int len = 0;
    int count = 0;

    if(!tar || !src) 
        return FAIL;

    tar->cmd_type = src->cmd_type;
    tar->cmd = src->cmd;
    tar->ack = src->ack;
    for (count = 0; count < DATA_MAX_NUM; count++) {
        if (src->data[count]) {
            len = strlen((char *)src->data[count]) + 1;
            tar->data[count] = (char *)malloc(len);
            strncpy((char *)tar->data[count], 
                    (char *)src->data[count],
                    len);
        }
    }

    return TRUE;
}